package jackson;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonStreamContext;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.SneakyThrows;

import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author 黄乾坤
 * @create 2023-07-06 10:38
 */
public class CustomSerializer extends JsonSerializer<Object> {

    private static final Map<String, List<Field>> cache = new ConcurrentHashMap<>();


    @Override
    public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        JsonStreamContext outputContext = jsonGenerator.getOutputContext();
        Class<?> aClass = o.getClass();
        if (outputContext.inRoot()) {
            List<Field> list = getFieldList(aClass);
            jsonGenerator.writeStartObject();
            if (list != null) {
                for (Field field : list) {
                    field.setAccessible(true);
                    if (!field.isAnnotationPresent(CustField.class)) {
                        try {
                            serializerProvider.defaultSerializeField(field.getName(), field.get(o), jsonGenerator);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                        continue;
                    }

                    if (field.getType()
                             .isPrimitive() || Number.class.isAssignableFrom(field.getType())) {
                        jsonGenerator.writeStringField(field.getName(), "111111");
                    } else {
                        try {
                            serializerProvider.defaultSerializeField(field.getName(), field.get(o), jsonGenerator);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            jsonGenerator.writeEndObject();
        } else if (outputContext.inObject()) {
            Object currentValue = outputContext.getCurrentValue();
            aClass = currentValue.getClass();
            List<Field> list = getFieldList(aClass);
            Field field = list.stream()
                              .filter(f -> f.getName()
                                            .equals(outputContext.getCurrentName()))
                              .findFirst()
                              .orElse(null);
            if (field != null) {
                field.setAccessible(true);
                if (field.isAnnotationPresent(CustField.class)) {
                    if (field.getType()
                             .isPrimitive() || Number.class.isAssignableFrom(field.getType())) {
                        jsonGenerator.writeString("1111111");
                    } else {
                        serializerProvider.defaultSerializeValue(o, jsonGenerator);
                    }
                } else {
                    serializerProvider.defaultSerializeValue(o, jsonGenerator);
                }
            }
        }else if(outputContext.inArray()){
//            jsonGenerator.writeStartArray();
//
//            jsonGenerator.writeEndArray();

//            JsonSerializer<Object> valueSerializer = serializerProvider.findValueSerializer(o.getClass());
//            valueSerializer.serialize(o, jsonGenerator, serializerProvider);

        }
    }

    private List<Field> getFieldList(Class<?> aClass) {
        List<Field> list = null;
        if(cache.get(aClass.getName()) != null){
            list = cache.get(aClass.getName());
        } else {
            Field[] fields = aClass.getDeclaredFields();

            list = Arrays.stream(fields).collect(Collectors.toList());
            cache.put(aClass.getName(), list);
        }
        return list;
    }
}
